package liming.tool.json;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ValueOf {
    // 集成PrimitiveConverter的转换能力
    private static final PrimitiveTypeConverter CONVERTER = new PrimitiveTypeConverter();
    private static final Map<Class<?>, DefaultValue<?>> DEFAULTS = new ConcurrentHashMap<>();

    static {
        // 初始化默认值配置（保留原有逻辑，略作优化）
        initDefaults();
    }

    private static void initDefaults() {
        // 对象类型默认值
        setDefault(Object.class, () -> null);
        setDefault(String.class, () -> "");

        // 布尔类型
        setDefault(Boolean.class, () -> false);
        setDefault(boolean.class, () -> false);

        // 字符类型
        setDefault(Character.class, () -> '\u0000');
        setDefault(char.class, () -> '\u0000');

        // 数值类型
        setDefault(Number.class, () -> 0);
        setDefault(Byte.class, () -> (byte)0);
        setDefault(Short.class, () -> (short)0);
        setDefault(Integer.class, () -> 0);
        setDefault(Long.class, () -> 0L);
        setDefault(Float.class, () -> 0.0f);
        setDefault(Double.class, () -> 0.0d);

        // 基本类型
        setDefault(byte.class, () -> (byte)0);
        setDefault(short.class, () -> (short)0);
        setDefault(int.class, () -> 0);
        setDefault(long.class, () -> 0L);
        setDefault(float.class, () -> 0.0f);
        setDefault(double.class, () -> 0.0d);

        // 集合类型
        setDefault(List.class, ArrayList::new);
        setDefault(ArrayList.class, ArrayList::new);
        setDefault(LinkedList.class, LinkedList::new);
        setDefault(Map.class, HashMap::new);
        setDefault(Set.class, HashSet::new);
        setDefault(JSONObject.class, JSONObject::new);
        setDefault(JSONArray.class, JSONArray::new);
    }

    public interface DefaultValue<T> {
        T get();
    }

    public static <T> void setDefault(Class<T> type, DefaultValue<T> provider) {
        DEFAULTS.put(type, provider);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getDefault(Class<T> type) {
        return (T) Optional.ofNullable(DEFAULTS.get(type))
                .orElse(() -> null)
                .get();
    }

    @SuppressWarnings("unchecked")
    public static <T> T valueOf(Class<T> targetType, Object value) {
        try {
            // 空值处理
            if (value == null) return getDefault(targetType);

            // 直接类型匹配
            if (targetType.isInstance(value)) {
                return (T) value;
            }

            // 特殊集合类型转换
            if (value instanceof Map && JSONObject.class.isAssignableFrom(targetType)) {
                return (T) new JSONObject((Map<?, ?>) value);
            }
            if (value instanceof JSONObject && Map.class.isAssignableFrom(targetType)) {
                return (T) ((JSONObject) value).toMap();
            }
            if (value instanceof Collection && JSONArray.class.isAssignableFrom(targetType)) {
                return (T) new JSONArray((Collection<?>) value);
            }
            if (value instanceof JSONArray && Collection.class.isAssignableFrom(targetType)) {
                return (T) ((JSONArray) value).toList();
            }

            // 使用增强的类型转换器
            return (T) CONVERTER.convert(targetType, value);
        } catch (Exception e) {
            return getDefault(targetType);
        }
    }

    /**
     * 增强的PrimitiveConverter（集成默认值处理）
     */
    private static class PrimitiveTypeConverter {
        private final Map<Class<?>, Class<?>> wrapperMap = new HashMap<Class<?>, Class<?>>(){
            {
                put(int.class, Integer.class);
                put(long.class, Long.class);
                put(double.class, Double.class);
                put(float.class, Float.class);
                put(boolean.class, Boolean.class);
                put(byte.class, Byte.class);
                put(short.class, Short.class);
                put(char.class, Character.class);

            }
        };

        public Object convert(Class<?> targetType, Object value) {
            Class<?> actualType = targetType.isPrimitive() ?
                    wrapperMap.get(targetType) : targetType;

            // 字符串转换
            if (value instanceof String) {
                return convertString(actualType, (String) value);
            }

            // 数值类型转换
            if (value instanceof Number) {
                return convertNumber(actualType, (Number) value);
            }

            // 布尔类型转换
            if (value instanceof Boolean) {
                return convertBoolean(actualType, (Boolean) value);
            }

            // 默认返回目标类型默认值
            return getDefault(actualType);
        }

        private Object convertString(Class<?> type, String value) {
            try {
                if (type == Boolean.class) return Boolean.parseBoolean(value);
                if (type == Character.class) return value.charAt(0);
                if (Number.class.isAssignableFrom(type)) {
                    return parseNumber(type, value);
                }
            } catch (Exception e) {
                // 转换失败返回默认值
            }
            return getDefault(type);
        }

        private Object convertNumber(Class<?> type, Number value) {
            if (type == Byte.class) return value.byteValue();
            if (type == Short.class) return value.shortValue();
            if (type == Integer.class) return value.intValue();
            if (type == Long.class) return value.longValue();
            if (type == Float.class) return value.floatValue();
            if (type == Double.class) return value.doubleValue();
            return getDefault(type);
        }

        private Object convertBoolean(Class<?> type, Boolean value) {
            if (type == Boolean.class) return value;
            return getDefault(type);
        }

        private Number parseNumber(Class<?> type, String value) {
            if (type == Byte.class) return Byte.parseByte(value);
            if (type == Short.class) return Short.parseShort(value);
            if (type == Integer.class) return Integer.parseInt(value);
            if (type == Long.class) return Long.parseLong(value);
            if (type == Float.class) return Float.parseFloat(value);
            if (type == Double.class) return Double.parseDouble(value);
            return 0;
        }
    }
}